package com.hitechbangla.fctu.base.aircraft;

import com.hitechbangla.fctu.base.radar.Detected;
import com.hitechbangla.fctu.base.radar.Radar;
import com.hitechbangla.fctu.utility.GeneralUtil;
import fctu.simulator.HTB_MAIN;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Asus
 */
public class AIRadar implements Serializable
{
    private Aircraft ownerAircraft;
    private Radar radar;
    private float range;
    private float radarAngle;
    private List<Aircraft> aircraftsInRange;
    private List<Aircraft> aircraftCheckList;
    
    private static final float heigtRange = 1000f;
    private static final float angleOneQuadrant = 90f;
    private static final float angleTwoQuadrant = 180f;
    private static final float angleFourQuadrant = 360f;
    
    public AIRadar(float range, float radarAngle, Radar radar)
    {
	//List<Aircraft> aclist = HTB_MAIN.gameScene.airCraftList;
	this.ownerAircraft = null;
	this.radarAngle = radarAngle;
	this.range = range;
	this.radar = radar;
	//aircraftsInRange = new ArrayList<>();
	aircraftCheckList = new ArrayList<>();
	
    } // end of constructor
    
    public boolean isAssignedToAnyAircraft()
    {
	return (!(this.ownerAircraft == null));	
    }
    
    
    
    public void draw(Graphics g)
    {
	update();	
	Graphics2D g2d = (Graphics2D)g;
	
	for(Aircraft aircraft: aircraftsInRange)
	{
	    Detected detectedAircraft = getDetected(aircraft);
	    int aircraftPositionX, aircraftPositionY, aircraftRect;
	    aircraftPositionX = (int)Math.round(detectedAircraft.getAcPosX() * HTB_MAIN.one_px_equivalent_naut);
	    aircraftPositionY = (int)Math.round(detectedAircraft.getAcPosY() * HTB_MAIN.one_px_equivalent_naut);
	    
	    aircraftRect = 6;

	    aircraftPositionX -= aircraftRect / 2;
	    aircraftPositionY -= aircraftRect / 2;	    
	      
	    g.setColor(Color.RED);
	    g2d.fillRect(aircraftPositionX, aircraftPositionY, aircraftRect, aircraftRect);
	}
    }
    
    
    
    private Detected getDetected(Aircraft aircraft)
    {
	for(Object objectDetected : this.radar.getDetectedMap().values())
	{
	    Detected detected = (Detected)objectDetected;
	    
	    if(detected.getAircraft().getAircraftState().getCallSign().equals(aircraft.getAircraftState().getCallSign()))
	    {
		return detected;
	    }
	}
	return null;
    }    
    
        
    public void update()
    {
	//List<Aircraft> listAircraftInSystem = HTB_MAIN.gameScene.airCraftList;
	aircraftsInRange = new ArrayList<>();	
	
	for(Aircraft aircraft: getAircraftCheckList())
	{
	    if(aircraft == this.ownerAircraft)
	    {
		continue;
	    }
	    if(checkOtherAircraftInRange(aircraft))		
	    {
		aircraftsInRange.add(aircraft);
		////System.out.println("from airadar : ONe aircraft added in Ai RAdar");
	    }
	}	
    } // end of update method
    
    
    private float checkHeadingForNegative(float heading)
    {
	if(heading<0)
	{
	    return 360 - Math.abs(heading);
	}
	else
	{
	    return heading;
	}
    }
    
    
    
    private  boolean checkOtherAircraftInRange(Aircraft otherAircraft)
    {
	if(inRange(otherAircraft))
	{
	    double headingWithOtherAircraft = getHeadingWithOtherAircraft(otherAircraft);
	    float angleLowerLimit = this.getOwnerAircraft().getAircraftState().getHeading() - this.getRadarAngle()/2;
	    float angleUpperLimit = this.getOwnerAircraft().getAircraftState().getHeading() + this.getRadarAngle()/2;
	    
	    angleLowerLimit = checkHeadingForNegative(angleLowerLimit);
	    angleUpperLimit = checkHeadingForNegative(angleUpperLimit);
	    
	    if(angleInRange(angleLowerLimit,angleUpperLimit,headingWithOtherAircraft))
	    {
		return true;
	    }
	    else
	    {
		return false;
	    }
	}
	else
	{
	    return false;
	}
    }
    
    public boolean angleInRange(float lowerLimit, float upperLimit, double heading)
    {
	if(upperLimit>lowerLimit)
	{
	    if((Math.round(heading)>=Math.round(lowerLimit)) && (Math.round(heading)<=Math.round(upperLimit)))
	    {
		return true;
	    }
	    else
	    {
		return false;
	    }
	}
	else
	{
	    if((Math.round(heading)>=Math.round(upperLimit)) && (Math.round(heading)<=Math.round(lowerLimit)))
	    {
		return false;
	    }
	    else
	    {
		return true;
	    }
	}
    }    
    
    private double getHeadingWithOtherAircraft(Aircraft otherAicraft)
    {
	double headingWithOther = GeneralUtil.getHeadingWithOther(this.getOwnerAircraft().getAircraftState().getLocation().getX(), this.getOwnerAircraft().getAircraftState().getLocation().getY(), otherAicraft.getAircraftState().getLocation().getX(), otherAicraft.getAircraftState().getLocation().getY());
	return headingWithOther;
    }
    
    
    private boolean inRange(Aircraft otherAircraft) // this method just checks angle range and height range with other aircraft
    {
	return (inRangeDistance(otherAircraft) && inRangeHeight(otherAircraft));	
    } // end of inRange method
    
    private boolean inRangeDistance(Aircraft otherAircraft)
    {
	double distX = this.getOwnerAircraft().getAircraftState().getLocation().getX() - otherAircraft.getAircraftState().getLocation().getX();
	double distY = this.getOwnerAircraft().getAircraftState().getLocation().getY() - otherAircraft.getAircraftState().getLocation().getY();
	
	double distance = (float)Math.sqrt(distX*distX + distY*distY);
	
	if(distance<this.getRange())
	{
	    return true;
	}
	else
	{
	    return false;
	}
    } // end of inRangeDistance method

    private boolean inRangeHeight(Aircraft otherAircraft)
    {
	double verticalDistance = Math.abs(this.ownerAircraft.getAircraftState().getLocation().getZ() - otherAircraft.getAircraftState().getLocation().getZ());
	
	if(verticalDistance<heigtRange)
	{
	    return true;
	}
	else
	{
	    return false;
	}
    } // end of inRangeHeight method
    
    /**
     * @return the ownerAircraft
     */
    public Aircraft getOwnerAircraft() {
	return ownerAircraft;
    }

    /**
     * @param ownerAircraft the ownerAircraft to set
     */
    public void setOwnerAircraft(Aircraft ownerAircraft) {
	this.ownerAircraft = ownerAircraft;
    }

    /**
     * @return the range
     */
    public float getRange() {
	return range;
    }

    /**
     * @param range the range to set
     */
    public void setRange(float range) {
	this.range = range;
    }

    /**
     * @return the radarAngle
     */
    public float getRadarAngle() 
    {
	return radarAngle;
    }

    /**
     * @param radarAngle the radarAngle to set
     */
    public void setRadarAngle(float radarAngle) {
	this.radarAngle = radarAngle;
    }

    /**
     * @return the aircraftsInRange
     */
    public List<Aircraft> getAircraftsInRange() {
	return aircraftsInRange;
    }

    /**
     * @param aircraftsInRange the aircraftsInRange to set
     */
    public void setAircraftsInRange(List<Aircraft> aircraftsInRange) {
	this.aircraftsInRange = aircraftsInRange;
    }
    
    /*
    public void draw(Graphics g)
    {
	////System.out.println("from ai radar : size of aircrafts in range is " + aircraftsInRange.size());
	////System.out.println("Okay in Ai radar");
	//g.drawRect(0, 0, 10, 10);
	
	if(aircraftsInRange == null)
	    return;
	for(Aircraft ac : aircraftsInRange)
	{
	    int x = (int) ac.getAircraftState().getLocation().getX();
	    int y = (int) ac.getAircraftState().getLocation().getY();	    
	    Color c = g.getColor();
	    g.setColor(Color.YELLOW);
	    g.drawRect(x-5, y-5, 10, 10);
	}//end for
	////System.out.println("from ai radar printed detected list");
	
    }//end of draw
    */
    /**
     * @return the aircraftCheckList
     */
    public List<Aircraft> getAircraftCheckList() {
	return aircraftCheckList;
    }
    
}
